﻿using LxBasic;
using System;

namespace LxCore
{
    public struct PhysicalFace
    {
        public Vector3d Normal;//lenth为面的面积
        public double gDiff;
        public double gT;
        private void cal_gDiff(Vector3d faceO2N)
        {
            double normalDotOToN = Vector3d.DotProduct(Normal, faceO2N);
            gDiff = Normal.LengthSquared() / normalDotOToN;
            gT = normalDotOToN / (faceO2N.LengthSquared());
        }
        public void SetFace(in DiagonalMatrixR3C3 diaMatrix, in FvInnFace face)
        {
            Normal = Matrix3dMath.Product(diaMatrix, face.Normal);
            cal_gDiff(face.OToN);
        }
        public void SetFace(in MatrixR3C3 matrix, in FvInnFace face)
        {
            Normal = Matrix3dMath.Product(matrix, face.Normal);
            cal_gDiff(face.OToN);
        }
        public void SetFace(in DiagonalMatrixR3C3 diaMatrix, in FvBouFace face)
        {
            Normal = Matrix3dMath.Product(diaMatrix, face.Normal);
            cal_gDiff(face.OToN);
        }
        public void SetFace(in MatrixR3C3 matrix, in FvBouFace face)
        {
            Normal = Matrix3dMath.Product(matrix, face.Normal);
            cal_gDiff(face.OToN);
        }
        private double calNonOrthogonalityCorrection(Vector3d aveGrad, Vector3d faceO2N, double phiN_phiO)
        {
            return Vector3d.DotProduct(aveGrad, Normal - gT * faceO2N) + phiN_phiO * (gT - gDiff);
        }
        public double CalNonOrthogonalityCorrectionOfInner(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)//公式整合
        {
            return calNonOrthogonalityCorrection(face.CalAverage(gradPhi), face.OToN, phi[face.NSideCell] - phi[face.OSideCell]);
        }
        public double CalNonOrthogonalityCorrectionOfBound(ref FvBouFace face, Vector3d[] gradPhi, double[] xInn, double xBou)
        {
            return calNonOrthogonalityCorrection(gradPhi[face.OSideCell], face.OToN, xBou - xInn[face.OSideCell]);
        }
    }
    public abstract class PhysicalFaceOld
    {
        public interface IPhysicalFace
        {
            void SetFace(ref DiagonalMatrixR3C3 diaMatrix, ref FvInnFace face);
            void SetFace(ref MatrixR3C3 matrix, ref FvInnFace face);
            double CalNonOrthogonalityCorrection_inner(ref FvInnFace face, Vector3d[] gradPhi, double[] x);
            double CalNonOrthogonalityCorrection_bound(ref FvInnFace face, Vector3d[] gradPhi, double[] x);
        }
        public struct MinCor : IPhysicalFace
        {
            public Vector3d Normal;//lenth为面的面积
            public double gDiff;
            private void cal_gDiff(ref FvInnFace face)
            {
                gDiff = Vector3d.DotProduct(Normal, face.OToN) / (face.OToNLength * face.OToNLength);
            }
            public void SetFace(ref DiagonalMatrixR3C3 diaMatrix, ref FvInnFace face)
            {
                Normal = Matrix3dMath.Product(diaMatrix, face.Normal);
                cal_gDiff(ref face);
            }
            public void SetFace(ref MatrixR3C3 matrix, ref FvInnFace face)
            {
                Normal = Matrix3dMath.Product(matrix, face.Normal);
                cal_gDiff(ref face);
            }
            private double calNonOrthogonalityCorrection(ref FvInnFace face, Vector3d aveGrad, double[] phi)
            {
                return Vector3d.DotProduct(aveGrad, Normal - gDiff * face.OToN);
            }
            public double CalNonOrthogonalityCorrection_inner(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)//公式整合
            {
                return calNonOrthogonalityCorrection(ref face, face.CalAverage(gradPhi), phi);
            }
            public double CalNonOrthogonalityCorrection_bound(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)
            {
                return calNonOrthogonalityCorrection(ref face, gradPhi[face.OSideCell], phi);
            }
        }
        public struct OrthCor : IPhysicalFace
        {
            public Vector3d Normal;//lenth为面的面积
            public double gDiff;
            public double gT;
            private void cal_gDiff(ref FvInnFace face)
            {
                gDiff = Normal.Length() / face.OToNLength;
                gT = Vector3d.DotProduct(Normal, face.OToN) / (face.OToNLength * face.OToNLength);
            }
            public void SetFace(ref DiagonalMatrixR3C3 diaMatrix, ref FvInnFace face)
            {
                Normal = Matrix3dMath.Product(diaMatrix, face.Normal);
                cal_gDiff(ref face);
            }
            public void SetFace(ref MatrixR3C3 matrix, ref FvInnFace face)
            {
                Normal = Matrix3dMath.Product(matrix, face.Normal);
                cal_gDiff(ref face);
            }
            private double calNonOrthogonalityCorrection(ref FvInnFace face, Vector3d aveGrad, double[] phi)
            {
                return Vector3d.DotProduct(aveGrad, Normal - gT * face.OToN) + (phi[face.NSideCell] - phi[face.OSideCell]) * (gT - gDiff);
            }
            public double CalNonOrthogonalityCorrection_inner(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)//公式整合
            {
                return calNonOrthogonalityCorrection(ref face, face.CalAverage(gradPhi), phi);
            }
            public double CalNonOrthogonalityCorrection_bound(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)
            {
                return calNonOrthogonalityCorrection(ref face, gradPhi[face.OSideCell], phi);
            }
        }
        public struct OverRelax : IPhysicalFace
        {
            public Vector3d Normal;//lenth为面的面积
            public double gDiff;
            public double gT;
            private void cal_gDiff(ref FvInnFace face)
            {
                double normalDotOToN = Vector3d.DotProduct(Normal, face.OToN);
                gDiff = Normal.LengthSquared() / normalDotOToN;
                gT = normalDotOToN / (face.OToNLength * face.OToNLength);
            }
            public void SetFace(ref DiagonalMatrixR3C3 diaMatrix, ref FvInnFace face)
            {
                Normal = Matrix3dMath.Product(diaMatrix, face.Normal);
                cal_gDiff(ref face);
            }
            public void SetFace(ref MatrixR3C3 matrix, ref FvInnFace face)
            {
                Normal = Matrix3dMath.Product(matrix, face.Normal);
                cal_gDiff(ref face);
            }
            private double calNonOrthogonalityCorrection(ref FvInnFace face, Vector3d aveGrad, double[] phi)
            {
                return Vector3d.DotProduct(aveGrad, Normal - gT * face.OToN) + (phi[face.NSideCell] - phi[face.OSideCell]) * (gT - gDiff);
            }
            public double CalNonOrthogonalityCorrection_inner(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)//公式整合
            {
                return calNonOrthogonalityCorrection(ref face, face.CalAverage(gradPhi), phi);
            }
            public double CalNonOrthogonalityCorrection_bound(ref FvInnFace face, Vector3d[] gradPhi, double[] phi)
            {
                return calNonOrthogonalityCorrection(ref face, gradPhi[face.OSideCell], phi);
            }
        }
    }
}
